package com.zhixue.ucenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.zhixue.ucenter.mapper.ZxMenuMapper;
import com.zhixue.ucenter.mapper.ZxUserMapper;
import com.zhixue.ucenter.model.dto.AuthParamsDto;
import com.zhixue.ucenter.model.dto.ZxUserExt;
import com.zhixue.ucenter.model.po.ZxMenu;
import com.zhixue.ucenter.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;


/**
 * @author Dragon
 * @description UserServiceImpl
 * @date 2023/10/15 19:46
 */

@Slf4j
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    ZxUserMapper zxUserMapper;

    @Autowired
    ZxMenuMapper zxMenuMapper;

    /**
     * spring容器
     */
    @Autowired
    ApplicationContext applicationContext;


    /**
     * 根据账号查询用户信息
     * @param s
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        AuthParamsDto authParamsDto = null;
        try {
            authParamsDto = JSON.parseObject(s, AuthParamsDto.class);
        } catch (Exception e) {
            log.error("认证请求数据格式不对：{}", s);
            throw new RuntimeException("认证请求数据格式不对");
        }
//        //账号
//        String username = authParamsDto.getUsername();
//        //根据username账号查询数据库
//        ZxUser zxUser = zxUserMapper.selectOne(new LambdaQueryWrapper<ZxUser>().eq(ZxUser::getUsername, username));
//
//        //查询到用户不存在，要返回null,spring security框架返回，由框架进行密码比对
//        if (zxUser == null) {
//            return null;
//        }
//        //如果查询到了用户的正确密码，最终封装成一个UserDetails对象给spring security框架返回，由框架进行密码比对
//        //取出数据库存储的正确密码
//        String password = zxUser.getPassword();
//
//        //用户权限,如果不加报Cannot pass a null GrantedAuthority collection
//        String[] authorities = {"test"};
//
//        //为了安全在令牌中不放密码
//        zxUser.setPassword(null);
//        //将user对象转json
//        String userString = JSON.toJSONString(zxUser);
//
//        //创建UserDetails对象,权限信息待实现授权功能时再向UserDetail中加入
//        UserDetails userDetails = User.withUsername(userString).password(password).authorities(authorities).build();
//
//        return userDetails;


        // 获取认证类型，beanName就是 认证类型 + 后缀，例如 password + _authservice = password_authservice
        String authType = authParamsDto.getAuthType();
        // 根据认证类型，从Spring容器中取出对应的bean
        AuthService authService = applicationContext.getBean(authType + "_authservice", AuthService.class);
        ZxUserExt user = authService.execute(authParamsDto);
        return getUserPrincipal(user);
    }


    private UserDetails getUserPrincipal(ZxUserExt user) {
        // 获取用户id
        String userId = user.getId();
        // 根据用户id查询用户权限
        List<ZxMenu> zxMenus = zxMenuMapper.selectPermissionByUserId(userId);
        ArrayList<String> permissions = new ArrayList<>();
        // 没权限，给一个默认的
        if (zxMenus.isEmpty()) {
            permissions.add("test");
        } else {
            // 获取权限，加入到集合里
            zxMenus.forEach(zxMenu -> {
                permissions.add(zxMenu.getCode());
            });
        }
        // 设置权限
        user.setPermissions(permissions);
        String[] authorities = permissions.toArray(new String[0]);
        //String[]authorities={"test"};
        String password = user.getPassword();
        user.setPassword(null);
        String userJsonStr = JSON.toJSONString(user);
        UserDetails userDetails = User.withUsername(userJsonStr).password(password).authorities(authorities).build();
        return userDetails;
    }

}
